package scuts.core;

using scuts.core.Flip;


class ReduceArr {
  
  public static function reduceLeftWithIndexToString <T>(a:Array<T>, f:String->T->Int->String):String
  {
    return ReduceArr.reduceLeftWithIndex(a, f, Std.string);
  }
  
  public static function reduceRightWithIndexToString <T>(a:Array<T>, f:T->String->Int->String):String
  {
    return ReduceArr.reduceRightWithIndex(a, f, Std.string);
  }
  
  public static function reduceLeftToString <T>(a:Array<T>, f:String->T->String):String
  {
    return ReduceArr.reduceLeft(a, f, Std.string);
  }
  
  public static function reduceRightToString <T>(a:Array<T>, f:T->String->String):String
  {
    return ReduceArr.reduceRight(a, f, Std.string);
  }
  
  public static function reduceLeft <T,S>(a:Array<T>, f:S->T->S, first:T->S):S
  {
    if (a.length == null) throw "Cannot reduce an empty Array";
    
    var acc = first(a[0]);
    for (i in 1...a.length) {
      acc = f(acc, a[i]);
    }
    return acc;
  }
  
  public static function reduceLeftWithIndex <T,S>(a:Array<T>, f:S->T->Int->S, first:T->S):S
  {
    if (a.length == null) throw "Cannot reduce an empty Array";
    
    var acc = first(a[0]);
    for (i in 1...a.length) {
      acc = f(acc, a[i],i);
    }
    return acc;
  }
  
  
  public static function reduceRight <T,S>(a:Array<T>, f:T->S->S, first:T->S):S
  {
    return ReduceArr.reduceLeft(a, f.flip(), first);
  }
  
  public static function reduceRightWithIndex <T,S>(a:Array<T>, f:T->S->Int->S, first:T->S):S
  {
    return ReduceArr.reduceLeftWithIndex(a, f.flip(), first);
  }
}